package com.liuyi.netty.im.commons.codes.serialize;

import cn.hutool.core.io.IoUtil;
import com.alibaba.fastjson.JSONObject;
import com.liuyi.netty.im.commons.codes.data.LimData;
import com.liuyi.netty.im.commons.codes.unusual.LimException;
import lombok.extern.slf4j.Slf4j;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Serializable;
import java.security.InvalidParameterException;
import java.util.HashMap;
import java.util.Map;

/**
 * 数据序列号管理器
 *
 * @author Mr.Fmy
 * @since 2021-11-26
 */
public class ContentTypeSerializeManage {

    private final static Map<Byte, ContentTypeSerializeHandle> D = new HashMap<>();

    public static void registered(Byte type, ContentTypeSerializeHandle handle) {
        D.put(type, handle);
    }

    public static ContentTypeSerializeHandle get(Byte type) {
        final ContentTypeSerializeHandle handle = D.get(type);
        if (handle == null) {
            throw new IllegalArgumentException("ContentType Error Not Handle Type：" + type);
        }
        return handle;
    }


    public static class FastJson implements ContentTypeSerializeHandle {

        @Override
        public <T extends LimData> T deserialization(byte[] content, Class<T> tClass) {
            if (tClass == null) {
                return null;
            }
            return JSONObject.parseObject(new String(content), tClass);
        }

        @Override
        public byte[] serialization(Object content) {
            return JSONObject.toJSONBytes(content);
        }
    }

    @Slf4j
    public static class Jdk implements ContentTypeSerializeHandle {

        @Override
        public <T extends LimData> T deserialization(byte[] content, Class<T> tClass) {
            try (ByteArrayInputStream inputStream = new ByteArrayInputStream(content)) {
                return IoUtil.readObj(inputStream, tClass);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                throw new LimException(e.getMessage());
            }
        }

        @Override
        public byte[] serialization(Object content) {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            if (!(content instanceof Serializable)) {
                throw new InvalidParameterException(content.getClass() + " Not Serializable");
            }
            IoUtil.writeObj(outputStream, true, (Serializable) content);
            return outputStream.toByteArray();
        }
    }
}
